Optimize function that does phrase-search and lists them
To improve the performance of code, a good plan is to:


Identify the hotspots, for example using profiling.
Prepare a representative test case and measure its performance.
Experiment with changes and see which ones improve the performace.


Step (2) is very important — if we don't have a representative test case then we might end up measuring the wrong thing. In this case I understand from the post that in the real program:


There are few sentences (tens), mostly 100 words or fewer.
There are many phrases (250,000), mostly with 5 words or fewer.
The matches are quite sparse (most sentences have no phrases).
The sentences change between calls to makeGsList but the phrases remain the same for each call.


So my test case is going to use your sentences list (8 elements is reasonably close to "10–20"), but I'm going to have to make my own phrases list, because you've only given me 7 elements which is nowhere near to 250,000.

&gt;&gt;&gt; words = [line.strip().lower() for line in open('/usr/share/dict/words')]
&gt;&gt;&gt; len(words)
235886
&gt;&gt;&gt; from random import sample, randrange
&gt;&gt;&gt; m_phrases = [' '.join(sample(words, randrange(1, 6))) for _ in range(250000)]


and then I'll time ten executions of makeGsList using Python's timeit module:

&gt;&gt;&gt; from timeit import timeit
&gt;&gt;&gt; timeit(lambda:makeGsList(sentences, 'm'), number=10)
2.7161848249379545


This is roughly similar to your reported results, so it might be representative enough. Now to try some changes.

First, let's tidy the code.


Instead of converting StartWords to a tuple for each sentence, convert it just once.
Instead of taking an org argument (and then checking it for each sentence), take a phrases argument.
Instead of maintaining a list gs_list2 and then converting it to a set to remove duplicates, maintain a set instead.


Revised code (this isn't noticeably faster, but it's in a better shape to work on):

def makeGsList2(sentences, phrases):
    "Return list of elements of phrases that appear in any of the sentences."
    start_words = tuple(StartWords)
    gs_set = set()
    for s in sentences:
        if s.startswith(start_words):
            s = s.lower()
            for phrase in phrases:
                if phrase in s:
                    gs_set.add(phrase)
    return list(gs_set)


It's clear that we have to avoid the loop over the phrases for each sentence. What we can do instead is to pre-process the phrases into a data structure that we can apply once to each sentence. What we need here is the Aho–Corasick algorithm. This isn't built into Python, but we could try one of the packages from PyPI. In the code below I'm using the pyahocorasick package; see the documentation for details.

import ahocorasick

def make_automaton(phrases):
    """Return an ahocorasick.Automaton that matches any of the phrases."""
    automaton = ahocorasick.Automaton()
    for phrase in phrases:
        automaton.add_word(phrase, phrase)
    automaton.make_automaton()
    return automaton

def makeGsList3(sentences, automaton):
    "Return list of unique matches of the automaton against the sentences."
    start_words = tuple(StartWords)
    gs_set = set()
    for s in sentences:
        if s.startswith(start_words):
            gs_set.update(phrase for _, phrase in automaton.iter(s.lower()))
    return list(gs_set)


Building the automaton takes a few seconds but it can be done just once for each list of phrases:

&gt;&gt;&gt; m_automaton = make_automaton(m_phrases)


And then the actual search is very quick:

&gt;&gt;&gt; timeit(lambda:makeGsList3(sentences, m_automaton), number=10)
0.0021720759104937315


This is about 1,200 times faster than the code in the post! Of course, this result only stands up to the extent that my test case is representative of the real system.