Remove use of numpy structured arrays in table operations

PR #2790 did not address the high-level table operations `hstack`, `vstack`, and `join`.  These are implemented in two-tiered approach: the low-level tier in `np_utils.py` used pure numpy structured arrays to do the heavy lifting while the high-level `operations.py` provided the Table interface.  The problem after #2790 is that these operations required creating temporary numpy structured arrays to represent the tables.

This PR updates the low-level code to do the operations directly with Table objects and largely eliminates use of numpy structured arrays.

In the current version of the PR, the module `np_utils.py` is basically orphaned, at least from the Table perspective.  The functions there were nominally public so we need to decide whether to deprecate them or just leave as a useful utility.
By design there is no real astropy dependency in `np_utils.py`, so it can be ripped out quite easily if needed.  So two options are:

- Copy `np_utils.py` (and `_np_utils.pyx`) to your project and use it.
- Ask the astropy devs about making this into a standalone package.

I don't know exactly how to say this in a deprecation message.