utils: add stacked matrix/{matrix,vector} products

Add two functions which interpret multi-dimension arrays as either
arrays of 2D matrices or arrays of vectors and find products between
them.

The functions make use of the numpy 'einsum' function which provides
very fast products on large arrays.
registration: refactor for speed

Thie is an API-breacking change. Instead of storing \tilde{Q} matrices
as arrays or array objects, move over to a multi-dimensional array
representation where the upper-triangular elements of the matrix are
stored directly in the last dimension.

This allows for a more efficient implementation of solvetransform()
which makes use of numpy's built in support for matrix stacks in
linalg.eigh.
registration: add example scripts

Add a couple of example tools which make use of the registration API.
Merge pull request #47 from rjw57/registration-refactor-for-merge

refactor registration code