Below is the figure I created using matplotlib. The problem is pretty obvious - the shortcuts overlap and all this is an unreadable mess.

I tried calling tight_layoutfor each subtitle, but this is a failure of my ipython-notebook kernel.
What can I do to fix the layout? Acceptable approaches include fixing xlabel, ylabel, and title for each subtitle, but another (and possibly better) approach would be to have one xlabel, label, and title for the whole image.
Here's the loop I used to create the above subplots:
for i, sub in enumerate(datalist):
subnum = i + start_with
subplot(3, 4, i)
xdat = sub['x'][(sub['in_trl'] == True) & (sub['x'].notnull()) & (sub['y'].notnull())]
ydat = sub['y'][(sub['in_trl'] == True) & (sub['x'].notnull()) & (sub['y'].notnull())]
hist2d(xdat, ydat, bins=1000)
plot(0, 0, 'ro')
title('Subject {0} in-Trial Gaze'.format(subnum))
xlabel('Horizontal Offset (degrees visual angle)')
ylabel('Vertical Offset (degrees visual angle)')
xlim([-.005, .005])
ylim([-.005, .005])
show()
Update:
Ok, so ImageGridit seems to be coming, but my figure still looks a bit awkward:

Here is the code I used:
fig = figure(dpi=300)
grid = ImageGrid(fig, 111, nrows_ncols=(3, 4), axes_pad=0.1)
for gridax, (i, sub) in zip(grid, enumerate(eyelink_data)):
subnum = i + start_with
xdat = sub['x'][(sub['in_trl'] == True) & (sub['x'].notnull()) & (sub['y'].notnull())]
ydat = sub['y'][(sub['in_trl'] == True) & (sub['x'].notnull()) & (sub['y'].notnull())]
gridax.hist2d(xdat, ydat, bins=1000)
plot(0, 0, 'ro')
title('Subject {0} in-Trial Gaze'.format(subnum))
xlabel('Horizontal Offset\n(degrees visual angle)')
ylabel('Vertical Offset\n(degrees visual angle)')
xlim([-.005, .005])
ylim([-.005, .005])
show()