Sensible distributed random seeding

This PR provides support for setting the random seed sensibly over the distributed engines.

Specifically, it provides a client-side `seed()` function, which sends the supplied seed to the generators on each engine, and then (optionally) makes a change to the state on each engine, based on the rank value, so that each engine's generator is in a different state (but still completely determined by the seed and rank).

If a seed of `None` is passed (or the seeding is omitted), then each generator will have a state based on whatever physical randomness the system supplied. This would give each engine a different state, but one not reproducible.

If another seed is passed (anything allowed by the usual `numpy.random.seed` is ok), then this seed is set on each engine. If `make_distinct=True`, the default, then each engine has its state scrambled in a way determined from the rank, so that each engine will be in a deterministic but different state. If a seed is passed, and `make_distinct=False`, then each engine is left in the same state, and so would generate the same sequence of numbers.

Tests for the above claims are included in the PR.

Closes #149.