1 - нарисуйте картинку для одномерного случая. Градиент превратится в обычную производную. Производная - это угол наклона касательной к нашей cost функции. Получается на этом шаге мы смотрим возрастает функция или нет (производная больше или меньше) и в зависимости от этого смещаемся в сторону, где функция меньше на размер шага(отсюда и название - градиентный спуск, мы спускаемся к минимуму функции используя градиент как направление). Для многомерного случая все так же, мы по сути делаем это для каждой переменной.
2 - чтобы не попасть на локальный минимум
Правильнее не использовать неподходящие структуры данных. В данном случае список - совершенно неподходящая структура данных. Используйте обычный двумерный массив. Как правило первый индекс оперирует колонками, второй столбцами.
Ваши кейсы решаются элементарно при помощи различных функций для работы с массивами (они есть во многих языках). Например для того чтобы оставить 1 и 5 можно использовать map.
Очевидно, что самый частый кейс - это отфильтровать строки по некоторому фильтру. Для этого ваша организация данных никуда не годится. А в случае с хранением строк - всё элементарно.
Ну вам же нужно во втором цикле КАЖДОЕ число из первого диапазона (с, d+1) умножить на КАЖДОЕ число из второго диапазона (a, b+1). Т.е. вам нужны вложенные циклы.
Примерно так:
for j in range(a, b + 1):
# здесь выводим значение из диапазона
print (j, '\t', end = '')
for i in range(c, d + 1):
# здесь считаем значения для каждой комбинации
print( i * j, '\t', end = '')
Я так понимаю, что вам вернет только авторизованных в вашем app пользователей. Так как это sandbox mode. Вы можете создать второй аккаунт, авторизовать его в вашем приложении и зафоловиться. sandbox mode раздел Sandbox Users