Infer names in MultiIndex.from_product if inputs have a name attribute
It would be convenient to have `from_product` infer level names from inputs if at all possible.

### Current behavior

```python
>>> a = pd.Series([1, 2, 3], name='a')
>>> b = pd.Series(['a', 'b'], name='b')

>>> pd.MultiIndex.from_product([a, b])
MultiIndex(levels=[[1, 2, 3], ['a', 'b']],
           codes=[[0, 0, 1, 1, 2, 2], [0, 1, 0, 1, 0, 1]])

```


### Current workaround

```python

>>> arrs = [a, b]
>>> pd.MultiIndex.from_product(ins, names=[el.name for el in arrs])
MultiIndex(levels=[[1, 2, 3], ['a', 'b']],
           codes=[[0, 0, 1, 1, 2, 2], [0, 1, 0, 1, 0, 1]],
           names=['a', 'b'])
```


Obviously this would't make sense for lists or arrays being passed in, but in the case of a `Series`, it would be nice to have the name persisted.

---

From glancing at the source, it looks like this would be somewhat simple to implement, the naive approach might be something like:

```
        from pandas.core.arrays.categorical import _factorize_from_iterables
        from pandas.core.reshape.util import cartesian_product

        if not is_list_like(iterables):
            raise TypeError("Input must be a list / sequence of iterables.")
        elif is_iterator(iterables):
            iterables = list(iterables)

        if names is None:
            names = [el.name if hasattr(el, 'name') else None for el in iterables]

        codes, levels = _factorize_from_iterables(iterables)
        codes = cartesian_product(codes)
        return MultiIndex(levels, codes, sortorder=sortorder, names=names)
```