More functions and cleanups for elephant

This pull request does 4 main things:

1. It implements the discussed improvements in the `isi` function.
2. It adds a `firing_rate` function.  Its purpose should be self-explanatory.
3. It adds a `conversion` module, which is intended for various functions that convert between different representations.  The only function right now is `binarize`, which was discussed previously.
4. It moves the `cv` function into its own `compat` module, where we can put other NeuroTools-related compatibility functions.

All of these, including API and names (and whether we should do 4 at all) are open to discussion.

I am also working on a `pandas` interface for `elephant`, with conversion between `neo` data types and `pandas` ones, as well as helper functions for using `elephant` functions with these and other `pandas` objects.  The functions are written but I don't have unit tests yet, so I will save that for a later pull request.
My thinking is that we wouldn't do anything explicit to support arguments
like `axis`.  If support comes more or less automatically from the
underlying functions, we can pass along the argument, as is the case here.
However, if it would take more than trivial work to support it, as is the
case with `binarize` (since `numpy.histogram` doesn't support it), we
shouldn't try to implement it ourselves unless there is a strong reason.

As for `DataFrame`, the primary advantage, at least to me, is pandas'
powerful handling of multiple parameters.  It has something called
[`MultiIndex`](
http://pandas.pydata.org/pandas-docs/dev/indexing.html#hierarchical-indexing-multiindex),
which allows you to set multiple indexes, of just about any type, to a
single row or column.  This, in practice, basically lets you map an
arbitrary number of dimensions to a 2D array, and then slice then and do
analyses on them very simply.  `pandas` also automatically handles padding
with `NaN` values and excluding `NaN` values from analyses, so working with
irregular length data like spike trains is no more difficult than
consistent data.

In the case of a spike train, imagine you have 5 factors in your
experiment, each with 5 values.  However, say that only some combinations
of parameters exist, and some combinations have multiple repetitions.  If
you use neo, your IO class can automatically load up these parameters, or
maybe you added them yourself.  If you convert this to a DataFrame, with
each row being the spike number and each column being a spike train, you
can set the column index of each spike train to be all of the parameters.
Then you can slice and manipulate those columns any way you want.

So, for example, say you want to plot the time of the first spike on the
y-axis, the value of a parameter named `param1` on the x-axis, and you want
one curve for each value of a parameter named `param2`, with error bars.
If you did this by hand, it would probably be dozens if not hundreds of
lines of code, depending on how the data is structured.  With pandas, it is
just:

```Python
df.min().groupby(level=['param1', 'param2']).aggregate(['mean', scipy.stats.sem]).unstack(level='param2').reset_index().plot(x='param1', y='mean', yerr='sem')
```

It looks complicated, but it is extremely powerful once you wrap your head
around it.  For me, where I have dozens of parameters scattered across
thousands of spike trains, only some of which vary in a given trial and
only a few of which I actually care about, it makes dealing with data
extremely easy.