Layout for a Tkinter form
Frames are specifically designed to be a tool in organizing the widgets in your GUI.

In the case of a simple form like this, I recommend using one frame for the labels and entries, and one for the buttons. grid is the natural choice for the form, and it looks like pack would be best for the buttons. pack is also best to put the form on top and the buttons on the bottom.

For the form, I would not use a frame for each row. 

Example:

# the root window and its children
form = tk.Frame(root)
buttons = tk.Frame(root)

form.pack(side="top", fill="both", expand=True)
buttons.pack(side="bottom", fill="x")

# the buttons
b1 = tk.Button(buttons, ...)
b2 = tk.Button(buttons, ...)

b1.pack(side="left", ...)
b2.pack(side="left", ...)

# the form
for row, field in enumerate(fields):
    lab = tk.Label(form, ...)
    ent = tk.Entry(form, ...)

    lab.grid(row=row, column=0, ...)
    ent.grid(row=row, column=1, ...)


The form can be thought of as a single complex widget. You can do that by creating a class for the form, based off of the Frame widget:

class Form(tk.Frame):
    def __init__(self, parent, fields):
        tk.Frame.__init__(self, parent)
        for row, field in enumerate(fields):
            ...


You would then use it like a normal frame when adding it to the window:

form = Form(root, fields=fields)
...
form.pack(side="top", fill="both", expand=True)


With that, you now have a general purpose form that could be reused for different purposes with different sets of fields.