feat: SimpleParallelChain
Oops, apologies. It should be fixed now. We should expect four files to have changed.
Similarly to how sequential chains connect chains in series, I thought we could have `ParallelChain`s connect chains in parallel. This is a useful abstraction when you want to independently process the same input with multiple different chains, possibly asynchronously (although I haven't added async yet). 

This was largely inspired by the `ConcatenateChain` example [here](https://langchain.readthedocs.io/en/latest/modules/chains/getting_started.html#create-a-custom-chain-with-the-chain-class), although I thought that it would be good to have a generic class for handling multiple chains in parallel, to make nested composition easier. The larger intent is to compose chains similar to how `nn.Sequential` and `nn.Parallel` allowed for composing neural modules in series and in parallel in Torch7.

Here is an example (which is added to the docs)

```
from langchain.llms import OpenAI
from langchain.prompts import PromptTemplate
from langchain.chains import LLMChain, SimpleParallelChain

llm = OpenAI(temperature=0.9)

prompt_1 = PromptTemplate(
    input_variables=["product"],
    template="What is a good name for a company that makes {product}?",
)
chain_1 = LLMChain(llm=llm, prompt=prompt_1)

prompt_2 = PromptTemplate(
    input_variables=["product"],
    template="What is a good slogan for a company that makes {product}?",
)
chain_2 = LLMChain(llm=llm, prompt=prompt_2)

parallel_chain = SimpleParallelChain(
    chains=[chain_1, chain_2],
    input_variables=['product'],
    output_variables=['name', 'slogan'],
    verbose=True
)
output = parallel_chain("colorful socks")
print(f"Output:\n{output}")
```
which produces the output:
```
> Entering new SimpleParallelChain chain...

> Finished chain.
Output:
{'product': 'colorful socks', 'name': '\n\nLively Sockery.', 'slogan': '\n\n"Step Into Color with Our Socks!"'}
```

If having a class like this would be useful, there a few design choices I'd love to discuss: 
1. Would it make more sense to have all the chains define their own input variables manually, or should we let the parallel chain define the input variables once and propagate that to all the child chains? An argument for the former would be that it follows the existing convention I've seen in defining chains so far. An argument for the latter would be that it would allow the user to define the input variables to the entire parallel block in one place (which would make the ParallelChain abstraction more powerful), without having to copy the same input variables for all child chains.
2. Any thoughts on whether it makes sense for this to be refactored in as a subcomponent of the MapReduceChain? The main reason for replacing the map component of the mapreduce by a ParallelChain would be that users can use ParallelChain for use cases other than applying the same llm for reducing a set of documents with the same prompt - they would instead be able to use multiple chains with different prompts each.
3. Any thoughts on how we would want to support multiple outputs for each child chain, i.e. how we would want to format the output of the ParallelChain? One possibility is to do a nested dict, like:
```
{
    'output_for_chain_1: {'chain_1_output_1': str, 'chain_1_output_2': str, ... },
    'output_for_chain_2: {'chain_2_output_1': str, 'chain_2_output_2': str, ... },
}
```
or flatten the keys with a delimiter, like:
```
{
    'output_for_chain_1/chain_1_output_1': str, 'output_for_chain_1/chain_1_output_2': str, ... },
    'output_for_chain_2/chain_2_output_1': str, 'output_for_chain_2/chain_2_output_2': str, ... },
}
```