Unexpected nan dtype changes when using DataFrame.replace

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


def timer(f):
    def wrapper(*arg, **karg):
        t_avg = []
        for i in range(10):
            t = time()
            ret = f(*arg, **karg)
            t = time() - t
            t_avg.append(t)
        t_avg = np.average(t_avg)
        print('Avg run time for {}: {}s'.format(f.__name__, t_avg))
        return ret
    return wrapper


# Creating the DataFrame
#--------------------------------------------------------
def random_replace(df, value, num_replace):
    for i in range(num_replace):
        x = np.random.randint(0, df.shape[0]-1)
        y = np.random.randint(0, df.shape[1]-1)
        df.iloc[x,y] = value
    return df

# Initialize df with True, add some False and nan values
df = pd.DataFrame(np.ones((1000,1000)))
df.iloc[:,:] = True
df = random_replace(df, float('nan'), 500)
# df = random_replace(df, np.nan, 500) # nan type can be float or np.nan; doesn't matter
df = random_replace(df, False, 500)


# Getting to the issue
#--------------------------------------------------------
@timer
def replace_with_list(df):
    df1 = df.replace([True, False], [1,0])
    return df1

@timer
def replace_individually(df):
    df2 = df.replace(True, 1)
    df2 = df2.replace(False, 0)
    return df2

# df.replace called individually for each replacement value is much faster
# as the size of the DataFrame gets large. Why?
df_list = replace_with_list(df)
df_indiv = replace_individually(df)

# Expect False because of the nan values:
(df_list == df_indiv).all().all()

# Expected True but returns False!
df_list.equals(df_indiv)

# Which values aren't equal?
df_list = df_list.values.flatten()
df_indiv = df_indiv.values.flatten()
not_equal_index = df_list != df_indiv

# All 'unequal' values are nans
pd.isnull(df_list[not_equal_index]).all()
pd.isnull(df_indiv[not_equal_index]).all()

# Why are nans from individual calls different than from the list call?
# Wouldn't it be best if they were the same?
np.isnan(df_list[not_equal_index]).all()
np.isnan(df_indiv[not_equal_index]).all()

# Looks list call results in np.nan whereas individual calls result in float('nan')?
type(df_list[not_equal_index][0])
type(df_indiv[not_equal_index][0])

```

#### Problem description

I'm experiencing some unexpected behavior in regards to NaN values from DataFrame.replace:
- When replace is called like: df = df.replace(True, 1); df = df.replace(False, 0)
the result should be the same as df = df.replace([True, False], [1,0]), right? the resultant DataFrame should be the same either way.
- However, when there are NaN values in the original df, df.replace seems to change the format of nans in the resultant DataFrame. 
- Additionally, I've noticed that calling df.replace n times for each value I wish to replace is much faster than calling df.replace once with lists of len(n). This seems kind of unideal.  

Thanks for all of your hard work Pandas devs! 

#### Expected Output
df_list.isequal(df_indiv) --> True

#### Output of ``pd.show_versions()``

INSTALLED VERSIONS
------------------
commit: None
python: 3.6.1.final.0
python-bits: 64
OS: Windows
OS-release: 10
machine: AMD64
processor: Intel64 Family 6 Model 58 Stepping 9, GenuineIntel
byteorder: little
LC_ALL: None
LANG: None
LOCALE: None.None

pandas: 0.20.1
pytest: 3.0.7
pip: 9.0.3
setuptools: 36.3.0
Cython: 0.28.1
numpy: 1.14.1
scipy: 1.0.0
xarray: None
IPython: 5.3.0
sphinx: 1.5.6
patsy: 0.4.1
dateutil: 2.6.1
pytz: 2017.3
blosc: None
bottleneck: 1.2.1
tables: 3.2.2
numexpr: 2.6.2
feather: None
matplotlib: 2.0.2
openpyxl: 2.4.7
xlrd: 1.0.0
xlwt: 1.2.0
xlsxwriter: 0.9.6
lxml: 3.7.3
bs4: 4.6.0
html5lib: 0.9999999
sqlalchemy: 1.1.9
pymysql: 0.7.11.None
psycopg2: None
jinja2: 2.9.6
s3fs: None
pandas_gbq: None
pandas_datareader: None

<details>

[paste the output of ``pd.show_versions()`` here below this line]

</details>
