Functions to convert camelCase strings to snake_case
A couple of things:


Why 2 functions?
Now that we established (1), you can get rid of the yields. 
yield is useful when you want to process stuff in chunks and do not want to wait for the entire population to be created first. This is not the case here.
There are some continues that do make sense and some that are redundant. Yours are of the latter type.
Nested if statements without corresponding else clauses can be merged with and if readability is not reduced.


Putting all that together, we get the following:

def cc2jl(my_str):
  """Camel case to joint-lower"""

  r = my_str[0].lower()
  for i, letter in enumerate(my_str[1:], 1):
    if letter.isupper():
      try:
        if my_str[i-1].islower() or my_str[i+1].islower():
          r += '_'
      except IndexError:
        pass
    r += letter.lower()
  return r

print(cc2jl('m'))                  #-&gt; m
print(cc2jl('AA'))                 #-&gt; aa
print(cc2jl('MySQLDatabase'))      #-&gt; my_sql_database
print(cc2jl('GarbageCollection'))  #-&gt; garbage_collection
print(cc2jl('AAAAAAAAAAAAAAAAA'))  #-&gt; aaaaaaaaaaaaaaaaa




Finally, some thoughts on avoiding the try block that bothers me personally.

We can leverage from the short-circuiting used in Python's logical expressions and (re-)write the following:

def cc2jl(my_str):
  """Camel case to joint-lower"""

  r = my_str[0].lower()
  for i, letter in enumerate(my_str[1:], 1):
    if letter.isupper():
      if my_str[i-1].islower() or (i != len(my_str)-1 and my_str[i+1].islower()):
        r += '_'
    r += letter.lower()
  return r


Note the i != len(my_str)-1 on the left side of the and. If this returns False the my_str[i+1] is not evaluated at all and thus cannot raise the IndexError.