Normalizing data over a distribution
For large datasets, avoid converting between native Python list and NumPy array objects as much as possible.  Look at the np.loadtxt and np.genfromtxt functions.  They may help you go from saved files of your data to NumPy arrays without having to make any Python lists at all.  But suppose you do have a Python list.  You shouldn't have to convert all of the data to a NumPy array, and then later convert each users's data to an array separately.  I would try something like this, assuming that np.loadtxt doesn't work for you:

data_lengths = [len(Xi) for Xi in X]
num_users = len(X)
max_length = max(data_lengths)
all_data = np.zeros(shape = (num_users, max_length), dtype = 'int')

for row, Xi in enumerate(X):
    row_length = len(Xi)
    all_data[row, 0:row_length] = Xi


From then on, every operation on your data should be an operation on a NumPy array instead of on a Python list.  The way I wrote it, it assumes your data are integers, and also that 0 can never occur as a real data point.  You can modify the dtype and offset of the call to np.zeros accordingly to meet the requirements of your particular data.

This approach will only be good if each user has a number of data points that is not too different from the number for the other users.  Other wise representing your data as a full matrix will be memory inefficient.
Use dtypes.  If your data are non-negative integers, for example, then np.bincount() will be much faster than np.histogram, for example.  Actually, if your data are integers, then you could probably just use collections.Counter() to make your histograms in native Python, which could also save time.