Dataframe.assign performance
#### Dataframe.assign performance

```python
import pandas as pd
import numpy as np
import time

def inplace_assign(df, **kwargs):
    for k, v in kwargs.items():
        df[k]=v
    return df

def functional_assign(df, **kwargs):
    ndf=df.copy(deep=False)
    return inplace_assign(ndf, **kwargs) 

if __name__=="__main__":
    N = 2 * 1000 * 1000
    df = pd.DataFrame(dict(a=np.zeros((N,)),b=np.arange(N), e=np.zeros((N,)), f=np.zeros((N,)),  g=np.zeros((N,)),  h=np.ones((N,)), i=np.ones((N,))))
    
    
    ta=0
    for i in range(10):
        t0 = time.time()
        for i in range(10):
            df.assign(c=df['b']*2)
        ta+=(time.time()-t0)
    print("PANDAS ASSIGN", ta)    

    
    ta=0
    for i in range(10):
        t0 = time.time()
        for i in range(10):
            functional_assign(df,c=df['b']*2)
        ta+=(time.time()-t0)
    print("FUNC ASSIGN", ta)
```
#### Problem description

Running the code fragment below on my computer outputs the following
```
# Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz
# pandas 0.23.4
PANDAS ASSIGN 1.5809710025787354
FUNC ASSIGN 0.43369007110595703
```

This suggests to me that assigns may be slower than it needs to be. 

Obviously, no-one really expects a simple alternate implementation of assign to beat the default implementation of a standard library unless there is something that I is overseen / a signficant drawbacks in the alternative implementation. I imagine that there may be reason for current choices. 

Although this has never been my understanding, I imagine that some users may consider that returning a new dataframe may mean a deep copy, and that may explain why current implementation is slower.
Ultimately, the pros and the cons of this alternative implementation certainly need to be considered too. 
If the speed up is confirmed (for different data and architecture), I imagine it may be good to change default implementation or to have an option offered when doing "assign" to eventually benefit from a faster implementation depending behaviour desired by user(deep/shallow copy)

Note: This can may be related to :
https://github.com/pandas-dev/pandas/issues/22126
