Use np.einsum in grad_lnlikelihood instead of a complex sum/map/dot mix

It makes for a 3x constant speedup for that line of code on my machine:

    In [1]: import numpy as np

    In [2]: alpha = np.random.randn(5000)

    In [3]: k = np.random.randn(5000, 5000)

    In [4]: %timeit sum(map(lambda r: np.dot(alpha, r), alpha[:, None] * k))
    10 loops, best of 3: 148 ms per loop

    In [5]: %timeit np.einsum('i,j,ji', alpha, alpha, k)
    10 loops, best of 3: 43.9 ms per loop

More importantly, I think it is also much more readable.
Precompute the matrix inverse for grad_lnlikelihood

This reduces the number of required operations for grad_lnlikelihood
by a factor equal to the number of kernel parameters.

e.g., consider this example:

	import numpy as np
	import george
	from george.kernels import Matern32Kernel, ConstantKernel, WhiteKernel

	x = 10 * np.random.RandomState(12356).rand(2000, 2)
	yerr = 0.2 * np.ones_like(x[:, 0])
	y = np.sin(x[:, 0] + x[:, 1]) + yerr * np.random.randn(len(x))

	kernel = ConstantKernel(0.5, ndim=2) * Matern32Kernel(0.5, ndim=2) + WhiteKernel(0.1, ndim=2)
	gp = george.GP(kernel, solver=george.HODLRSolver)
	gp.compute(x)

	%time gp.grad_lnlikelihood(y)

Before this change, I get:

	CPU times: user 8.89 s, sys: 479 ms, total: 9.37 s
	Wall time: 9.37 s
	array([-182.28430864,  208.82577854, -463.12445191])

After this change:

	CPU times: user 3.37 s, sys: 273 ms, total: 3.64 s
	Wall time: 3.64 s
	array([-182.27545648,  209.89776176, -479.34696447])

So it's a factor of three speedup, corresponding to the three parameters. There is
a similar speedup for basic solver (which for this problem size is actually faster,
at least on my laptop, perhaps because scipy's cholesky factorization can use
multi-processing).
Remove loop for grad_lnlikelihood calculation

The result (using einsum) is cleaner and perhaps slightly faster.
temp
Merge branch 'speedup-grad' of https://github.com/shoyer/george
slight refactor of grad computation
remove extra assert