I have the following code:

```
import pandas as pd
import time

def enrich_str(str):

    val1 = f'{str}_1'
    val2 = f'{str}_2'
    val3 = f'{str}_3'
    time.sleep(3)

    return val1, val2, val3

def enrich_row(passed_row):
    col_name = str(passed_row['colName'])
    my_string = str(passed_row[col_name])

    val1, val2, val3 = enrich_str(my_string)

    passed_row['enriched1'] = val1
    passed_row['enriched2'] = val2
    passed_row['enriched3'] = val3

    return passed_row

df = pd.DataFrame({'numbers': [1, 2, 3, 4, 5], 'colors': ['red', 'white', 'blue', 'orange', 'red']}, 
                  columns=['numbers', 'colors'])

df['colName'] = 'colors'

tic = time.perf_counter()
enriched_df = df.apply(enrich_row, col_name='colors', axis=1)
toc = time.perf_counter()

print(f"{df.shape[0]} rows enriched in {toc - tic:0.4f} seconds")

enriched_df

```

It takes 15 seconds to get the output dataframe like the following one:

[![enter image description here](https://i.stack.imgur.com/WZAC8.png)](https://i.stack.imgur.com/WZAC8.png)

Now I want to parallelize the enrichment operation using multiple threads on my machine.
I explored a lot of solution, like `Dask`, `numba`, but none of them seems strightforward to me.

Then I stumbled upon the `multiprocessing` library and its `pool.imaps()` method. So I tried to run the following code:

```
import multiprocessing as mp

tic = time.perf_counter()
pool = mp.Pool(5)
result = pool.imap(enrich_row, df.itertuples(), chunksize=1)
pool.close()
pool.join()
toc = time.perf_counter()

print(f"{df.shape[0]} rows enriched in {toc - tic:0.4f} seconds")
result

```

It takes about 2 seconds and `result` isn't a Pandas dataframe.
I can't figure out where I'm going wrong.