I might be tempted to use plt.annotate
to draw labelled arrows:
import numpy as np
import matplotlib.pyplot as plt
time = np.linspace(1500, 2000)
yvals = np.exp(time * 0.01)
myLabels = {1500:'Awful times', 1800:'Somewhat better times',
1930:'Bad again', 1990:'We are alright'}
fig, ax = plt.subplots(1, 1)
ax.plot(time, yvals)
for x, label in myLabels.iteritems():
ax.annotate(label, xy=(x, np.exp(x * 0.01)), xytext=(-40, 40),
xycoords='data', textcoords='offset points',
ha='center', va='bottom', fontsize='large',
arrowprops=dict(arrowstyle='->', lw=2))
ax.set_xlim(1300, 2100)
ax.set_ylim(0, yvals.max() * 1.2)

From the comments it seems you want to represent ranges of values on the time axis rather than single timepoints, and you want to plot multiple series on the same set of axes (so you don't want any aspect of the annotation to vary with the y-values of the timeseries).
There are really lots of ways you could do this, and I'm still not quite sure what you're looking for. One fairly straightforward option would be to plot colored shaded regions using plt.axvspan
(similar to chepyle's answer, except without varying the height) and use a legend to display the labels:
edges, labels = zip(*sorted(myLabels.iteritems()))
edges = edges + (2000,)
colors = ['r', 'b', 'g', 'c']
for ii, ll in enumerate(labels):
ax.axvspan(edges[ii], edges[ii + 1], facecolor=colors[ii],
label=labels[ii], alpha=0.3)
ax.legend(loc='upper left')

Using a legend has the advantage that you don't need to worry about cramming in a text label for the last range, which is quite narrow.
You could also use vertical lines and squeeze the labels in above (optionally with double-ended arrows to represent the ranges):
from matplotlib.transforms import blended_transform_factory
# x-position specified in data coordinates, y-position specified in [0, 1]
# relative axis coordinates
tform = blended_transform_factory(ax.transData, ax.transAxes)
edges, labels = zip(*sorted(myLabels.iteritems()))
edges = np.r_[edges, 2000]
centers = (edges[:-1] + edges[1:]) / 2.
# mark edges with dashed lines
for ee in edges:
ax.axvline(ee, ymax=0.75, ls='--', c='k')
# plot labels
for cc, ll in zip(centers, labels):
ax.annotate(ll, xy=(cc, 0.75), xytext=(0, 10),
xycoords=tform, textcoords='offset points',
ha='left', va='bottom', rotation=60)
# plot double-ended arrows
for start, stop in zip(edges[:-1], edges[1:]):
ax.annotate('', xy=(start, 0.75), xytext=(stop, 0.75),
xycoords=tform, textcoords=tform,
arrowprops=dict(arrowstyle='<->', lw=2, shrinkA=0, shrinkB=0))
# turn off spines and ticks on the top and right, so that they don't overlap
# with the labels
for sp in ('top', 'right'):
ax.spines[sp].set_visible(False)
ax.tick_params(top=False, right=False)
# rescale the y-axis so that the labels and arrows are positioned nicely relative
# to the line
ax.set_ylim(0, yvals.max() * 1.4)

This method requires a lot more tweaking in order to fit the labels in without overlapping one another or the axis spines.