Allow itertuples to return subsets of columns
#### Problem description

`pd.DataFrame.itertuples()` returns tuples/named tuples containing all columns and possibly the index. This is very inefficient if the DataFrame has many columns but you only need values of a few.

We should add an optional `columns` parameter to specify a subset of columns to return. The columns can be referred to by name or by position (if integer). Names can also refer to MultiIndex levels if no column matches. 

This give a speedup nearly proportional to the fraction of columns selected. Here are my results on on a DataFrame with 68 columns and 3.4m rows:

- Iterating with all columns: as namedtuples: 14.5 sec; as tuples: 11.9 sec.
- Iterating with just 6 columns: as named tuples: 2.4 sec; as tuples: 0.9 sec.

A 15-fold speed increase is definitely worthwhile!
 
##### Suggested solution

Here is my first go at a solution. Needs examples in docstring and unit tests. 

I plan on committing this during the European Pandas Sprint on 1-3 Feb  (https://python-sprints.github.io/europandas2019/), along with an itertuples doc issue (https://github.com/pandas-dev/pandas/issues/23848).

```python
def itertuples(self, index=True, name="Pandas", columns=None):
    """
    Iterate over DataFrame rows as namedtuples, with index value as first
    element of the tuple.

    Parameters
    ----------
    index : boolean, default True
        If True, return the index as the first element of the tuple.
    name : string, default "Pandas"
        The name of the returned namedtuples or None to return regular
        tuples.
    columns : optional list of strings/integers
        If provided, return just these columns, indexed by name or position.
        Names may match a column or a MultiIndex row index name. 
        
    Notes
    -----
    The column names will be renamed to positional names if they are
    invalid Python identifiers, repeated, or start with an underscore.
    With a large number of columns (>255), regular tuples are returned.

    See also
    --------
    iterrows : Iterate over DataFrame rows as (index, Series) pairs.
    iteritems : Iterate over (column name, Series) pairs.

    Examples
    --------

    >>> df = pd.DataFrame({'col1': [1, 2], 'col2': [0.1, 0.2]},
                          index=['a', 'b'])
    >>> df
       col1  col2
    a     1   0.1
    b     2   0.2
    >>> for row in df.itertuples():
    ...     print(row)
    ...
    Pandas(Index='a', col1=1, col2=0.10000000000000001)
    Pandas(Index='b', col1=2, col2=0.20000000000000001)

    """
    arrays = []
    fields = []
    if index:
        arrays.append(self.index)
        fields.append(self.index.name or "Index")
        
    if columns is not None:
        for f in columns:
            if f in self.index.names:
                vals = self.index.get_level_values(f)
            elif isinstance(f, int):
                vals = self.iloc[:,f]
                f = self.columns[f]
            else:
                vals = self.loc[:,f]
            arrays.append(vals)
            fields.append(f)
    else:
        # use integer indexing because of possible duplicate column names
        arrays.extend(self.iloc[:, k] for k in range(len(self.columns)))
        fields.extend(self.columns)
        
    # Python 3 supports at most 255 arguments to constructor, and
    # things get slow with this many fields in Python 2
    if name is not None and len(fields) < 256:
        # `rename` is unsupported in Python 2.6
        try:
            itertuple = collections.namedtuple(name,
                                               fields,
                                               rename=True)
            return map(itertuple._make, zip(*arrays))
        except Exception:
            pass

    # fallback to regular tuples
    return zip(*arrays)
```
